﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.IO.Ports;
using System.Windows.Forms;
using System.Threading;

namespace IAP_Update
{
    class Uart
    {
        //  声明获取当前时间函数
        [DllImport("KERNEL32.dll", CharSet = CharSet.Auto, EntryPoint = "GetTickCount")]
        public static extern uint GetTickCount();
 #region"变量定义"
        public const int OVERTIME = 2000;//通讯超时时间 2000mS
        public static SerialPort oSerialPort = new SerialPort();//定义串口类对象  


        public struct UartInfo
        {
            public string portName;//串口名
            public Int32 bandRate;//波特率 
            public Int32 dataBits;//数据位         
            public string stopBits;//停止位
            public string parity;//奇偶校验位

            public byte[] rcvBuffer;//接收缓冲区
            public byte[] sendBuffer;//发送缓冲区    
            public int sendCount;
            public int rcvCount;
        }
        public static UartInfo gUartInfo;

        public static bool gDataUpdateFlag;
 #endregion "变量定义"

        #region"串口连接"
        public void UART_Connect(string p_SerialPorts, int p_BaudRate)
        {
            try
            {
                if (string.IsNullOrEmpty(p_SerialPorts) || (p_BaudRate == 0))
                    return;
                oSerialPort.Close(); //关闭串口   
                oSerialPort.PortName = p_SerialPorts;//串口号  
                oSerialPort.BaudRate = p_BaudRate;//波特率 
                oSerialPort.StopBits = StopBits.One;//1位停止位
                oSerialPort.DataBits = 8;//8为数据位
                oSerialPort.Parity = Parity.None;//无校验  

                //oSerialPort.ReadBufferSize = 4096;//设置 SerialPort 输入缓冲区的大小
                //oSerialPort.WriteBufferSize = 2032;//设置串行端口输出缓冲区的大小
                if (!oSerialPort.IsOpen)//判断串口状态
                    oSerialPort.Open();//打开串口操作                 
            }
            catch (Exception ex)
            {
                MessageBox.Show("没有发现此串口或被占用!" + ex.Message.ToString(), "系统信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
        #endregion

        #region"串口发送数据"
        /// <summary>
        /// 发送
        /// </summary>
        public void UART_Transport(int lens)
        {
            try
            {
                oSerialPort.DiscardOutBuffer();//清空发送缓冲区     
                oSerialPort.DiscardInBuffer();//清空接收缓冲区
                oSerialPort.Write(gUartInfo.sendBuffer, 0, lens);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }
        public void UART_Transport(byte[] buffer) //Transport data
        {
            try
            {
                int len = buffer.Length;
                //GlobalVariables.txCount += len;//记录发送数据个数
                oSerialPort.DiscardOutBuffer();//清空发送缓冲区     
                oSerialPort.DiscardInBuffer();//清空接收缓冲区
                oSerialPort.Write(buffer, 0, len);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }
        #endregion

        #region"串口接收数据"
        /// <summary>
        /// 需要提前知道接数据长度，使用不方便
        /// 当前使用SerialPort类中提供myserialPort_DataReceived事件接收数据
        /// </summary>
        public bool UART_Receive(int pLens)
        {
           long Temp;
           byte[] TT=new byte[1];
           //GlobalVariables.rxCount += pLens; //接收数据个数
           try
           {
                gUartInfo.rcvBuffer = new byte[pLens];     
                Temp = GetTickCount();
                //获取当前时间
                for (int i = 0; i < pLens; i++)
                {
                    while (true)//等待
                    {
                        if (oSerialPort.BytesToRead > 0)     //接收缓冲区字符数
                        {
                            oSerialPort.Read(TT, 0, 1); //取出串口接收缓冲器的数据
                            gUartInfo.rcvBuffer[i] = TT[0];
                            break;
                        }
                        if ((GetTickCount() - Temp) > OVERTIME) //time out                                      
                            return false;
                        Application.DoEvents();
                        Thread.Sleep(10);
                    }
                }
                return true;
           }
           catch (Exception ex)
           {
               Console.WriteLine(ex.Message.ToString());
               return false;
           }
        }
        #endregion

        #region"发送复位码"
        //   0 发送复位码(重启或进入upgrade)
        public bool RstSystem()
        {
            gUartInfo.rcvCount = 0;//待接收数据个数

            byte[] bufTemp = new byte[5];
            bufTemp[0] = (byte) '`';

            UART_Transport(bufTemp);//发送数据
            Thread.Sleep(20);
            Application.DoEvents();
            return true;
        }
        #endregion

        #region"发送引导码"
        //   1 发送引导码(握手)
        public bool ShakeHands()
        {
            int ErrReceiveCount = 0;
            gUartInfo.rcvCount = 5;//待接收数据个数

            byte[] bufTemp = new byte[5];
            bufTemp[0] = 0xAA;
            bufTemp[1] = 0x01;
            bufTemp[2] = 0x00;
            bufTemp[3] = 0xC1;
            bufTemp[4] = GlobalMethods.BCC_Check(bufTemp);            
        Transport:
            UART_Transport(bufTemp);//发送数据
            Thread.Sleep(20);
            Application.DoEvents();
            if (!UART_Receive(gUartInfo.rcvCount))//接收失败
            {
                ErrReceiveCount++;
                if (ErrReceiveCount < 3)
                {
                    goto Transport;
                }
                else
                {
                    //MessageBox.Show("和下位机通讯失败！", "系统信息", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    ErrReceiveCount = 0;
                    return false;
                }
            }
            if (gUartInfo.rcvBuffer[gUartInfo.rcvCount - 1] != GlobalMethods.BCC_Check(gUartInfo.rcvBuffer))
            {
                return false;
            }
            return true;
        }
        #endregion


        #region"发送文件大小以及次数"
        //2 发送文件大小以及次数
        public bool BinFileSizeFrequency(int fileLength, int totalFrequency)
        {
            int errReceiveCount = 0;
            gUartInfo.rcvCount = 5;//待接收数据个数
            byte[] bufTemp = new byte[8];
            bufTemp[0] = 0xAA;//起始码
            bufTemp[1] = 0x03;//数据长度低字节;
            bufTemp[2] = 0x00;//数据长度高字节
            bufTemp[3] = 0xC2;//命令;
            bufTemp[4] = (byte)(fileLength / 256);//bin数据大小高位;
            bufTemp[5] = (byte)(fileLength % 256);//bin数据大小低位;        
            bufTemp[6] = (byte)totalFrequency;//发送次数
            bufTemp[7] = GlobalMethods.BCC_Check(bufTemp);//验证码 
        Transport:
            UART_Transport(bufTemp); ;//发送数据
            Thread.Sleep(20);
            Application.DoEvents();
            if (!UART_Receive(gUartInfo.rcvCount))//接收失败
            {
                errReceiveCount++;
                if (errReceiveCount < 3)
                {
                    goto Transport;
                }
                else
                {
                    //MessageBox.Show("和下位机通讯失败！", "系统信息", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    errReceiveCount = 0;
                    return false;
                }
            }
            //BCC异或校验      
            if ((gUartInfo.rcvBuffer[gUartInfo.rcvCount - 1] != GlobalMethods.BCC_Check(gUartInfo.rcvBuffer)) || (gUartInfo.rcvBuffer[3] == 0x3E))
                return false;

            return true;
        }
        #endregion


        #region"发送用户程序数据"
        public bool UserProgramData(byte[] p_parm)
        {
            int errReceiveCount = 0;
            int packetLength = p_parm.Length;
            int transportCount = packetLength + 5;//发送数据个数
            gUartInfo.rcvCount = 5;//待接收的数据个数

            byte[] bufTemp = new byte[transportCount];
            bufTemp[0] = 0xAA;          
            //数据包长度
            //bufTemp[1] = (byte)(packetLength & 0xff);//低8位
            //bufTemp[2] = (byte)((packetLength & 0xff) >> 8);//高8位
            bufTemp[1] = (byte)((packetLength + 1) % 256);//低位
            bufTemp[2] = (byte)((packetLength + 1) / 256);//高位;
            //命令
            bufTemp[3] = 0xC3;
            //数据包
            for (int i = 0; i < packetLength; i++)
            {
                bufTemp[4 + i] = p_parm[i];
            }
            //校验
            bufTemp[transportCount - 1] = GlobalMethods.BCC_Check(bufTemp);//求和校验
        Transport:
            UART_Transport(bufTemp);//发送数据
            Thread.Sleep(20);
            Application.DoEvents();

            if (!UART_Receive(gUartInfo.rcvCount))//接收失败
            {
                errReceiveCount++;
                if (errReceiveCount < 5)
                {
                    goto Transport;
                }
                else
                {
                    //MessageBox.Show("和下位机通讯失败！", "系统信息", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    errReceiveCount = 0;
                    return false;
                }
            }
            //BCC异或校验      
            if ((gUartInfo.rcvBuffer[gUartInfo.rcvCount - 1] != GlobalMethods.BCC_Check(gUartInfo.rcvBuffer)) || (gUartInfo.rcvBuffer[3] == 0x3E))
                return false;

            return true;
        }
        #endregion

    }
}
